package com.xiaoban.config;

import com.xiaoban.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @Title: SecurityConfig
 * @Author @小班哥
 * @Package com.xiaoban.config
 * @Date 2024/3/14 14:16
 * @description: Security配置类
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;


    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    private AccessDeniedHandler accessDeniedHandler;

    /**
     * 获取密码加密器的方法，用于生成 BCryptPasswordEncoder 实例。
     * BCryptPasswordEncoder 是 Spring Security 中常用的密码加密器，
     * 它使用 BCrypt 算法对密码进行加密，是一种安全性较高的加密方式。
     *
     * @return BCryptPasswordEncoder 实例
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 返回一个 BCryptPasswordEncoder 实例作为密码加密器
        return new BCryptPasswordEncoder();
    }


    /**
     *获取认证管理器的方法，用于在 Spring Security 配置中获取认证管理器实例。
     * 这个方法主要是为了在配置 Spring Security 时能够获取到 AuthenticationManager 实例，
     * 通常用于配置认证过程或者在其他地方需要使用认证管理器的场景。
     * @return 认证管理器实例
     * @throws Exception 如果获取认证管理器过程中出现异常
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    /**
     * 配置 HTTP 请求安全规则的方法，定义了关闭 CSRF、不使用 Session 获取 SecurityContext，并配置了接口权限规则。
     *
     * @param http HttpSecurity 对象，用于配置 HTTP 安全规则
     * @throws Exception 配置过程中可能抛出的异常
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // 关闭 CSRF 防护
                .csrf().disable()
                // 设置不使用 Session 获取 SecurityContext，即 STATELESS 模式
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                // 对于登录接口允许匿名访问，不需要认证即可访问
                .antMatchers("/user/login").anonymous()
                //基于配置的权限控制
//                .antMatchers("/testCors").hasAnyAuthority("system:dept:list")
                // 除登录接口外的所有请求都需要认证鉴权
                .anyRequest().authenticated();
            //把token校验过滤器添加到过滤器链中
            http.addFilterBefore(jwtAuthenticationTokenFilter , UsernamePasswordAuthenticationFilter.class);

            //配置异常处理器
        http.exceptionHandling()
            //认证失败处理器
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler);
        //允许跨域
//        http.csrf();
    }

}
